package com.axonactive.yolo.controller;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;

import org.apache.log4j.Logger;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.axonactive.yolo.domain.Airline;
import com.axonactive.yolo.domain.Task;
import com.axonactive.yolo.domain.TaskUserId;
import com.axonactive.yolo.dto.Flight;
import com.axonactive.yolo.dto.Parameters;
import com.axonactive.yolo.dto.TaskDTO;
import com.axonactive.yolo.exception.TaskNotFoundException;
import com.axonactive.yolo.exception.TaskUserIdNotFoundException;
import com.axonactive.yolo.monitor.ServiceProvider;
import com.axonactive.yolo.service.interfaces.AirlineService;
import com.axonactive.yolo.service.interfaces.ExchangeRateService;
import com.axonactive.yolo.service.interfaces.SubscribedFlightService;
import com.axonactive.yolo.service.interfaces.TaskService;
import com.axonactive.yolo.service.interfaces.TaskUserIdService;
import com.axonactive.yolo.service.interfaces.UserService;
import com.axonactive.yolo.service.internal.FlightFactoryService;
import com.axonactive.yolo.service.internal.FlightRequesterService;
import com.axonactive.yolo.util.CONSTANTS;
import com.axonactive.yolo.util.IOUtil;
import com.axonactive.yolo.util.Utils;
import com.axonactive.yolo.util.session.SessionHelper;
import com.axonactive.yolo.validation.TaskValidator;

@Controller
@RequestMapping("/task")
@PropertySource("classpath:messages.properties")
public class TaskController {

	private static final String PROPERTY_DAY_RETURN_INCORRECT = "inBound.cannotParseDate";
	private static final String PROPERTY_INBOUND_LESS_THAN_OUTBOUND = "inBound.lessThanOutBound";
	private static final String PROPERTY_TOKEN_DILEMITER = "token.delimiter";
	private static final String PROPERTY_TASK_CREATE_SUCCESS = "task.create.success";
	private static final String PROPERTY_TASK_WASNT_CREATE_SUCCESS = "task.create.not.success";
	private static final String PROPERTY_TASK_UPDATE_SUCCESS = "task.update.success";
	private static final String PROPERTY_TASK_UPDATE_NOT_SUCCESS = "task.update.not.success";
	private static final String PROPERTY_TASK_UPDATE_NOT_FOUND = "task.update.not.found";
	private static final String PROPERTY_TASK_ALREADY_CREATED = "task.already.created";

	@Resource
	private Environment env;

	@Autowired
	private TaskService taskService;

	@Autowired
	private TaskUserIdService taskUserIdService;

	@Autowired
	private UserService userService;

	@Autowired
	private AirlineService airlineService;

	@Autowired
	private SubscribedFlightService subcribedFlightService;

	@Autowired
	private ExchangeRateService exchangeRateService;

	@Autowired
	private TaskValidator taskValidator;

	private static Logger LOGGER = Logger.getLogger(TaskController.class);

	@InitBinder("parameters")
	private void taskValidator(WebDataBinder binder) {
		binder.setValidator(taskValidator);
	}

	private void initService() {
		ServiceProvider serviceProvider = ServiceProvider.getInstance();
		serviceProvider.injectService(exchangeRateService);
	}

	@RequestMapping(value = "/list", method = RequestMethod.GET)
	public ModelAndView getTaskList(HttpSession session) {
		if (!SessionHelper.isLoggedIn(session)) {
			SessionHelper.setGoBackTaskpage(session, true);
			return new ModelAndView("redirect:/account/login.html");
		}

		ModelAndView mav = new ModelAndView("task/list");
		int userId = SessionHelper.getUserId(session);

		// create task list from db
		List<TaskUserId> taskUserIds = taskUserIdService.findByUserId(userId);
		List<TaskDTO> tasks = new ArrayList<>();
		TaskDTO taskDTO;
		Task task;
		LOGGER.info("taskUserIds size: " + taskUserIds.size());
		for (int i = 0; i < taskUserIds.size(); i++) {
			taskDTO = new TaskDTO();
			task = taskService.findByTaskId(taskUserIds.get(i).getTaskId());
			taskDTO = taskDTO.getTaskDTO(task, taskUserIds.get(i));
			taskDTO.setId(i);

			tasks.add(taskDTO);
		}

		TaskDTO temp = null;
		for (int i = 0; i < tasks.size() / 2; i++) {
			temp = tasks.get(i);
			tasks.set(i, tasks.get(tasks.size() - i - 1));
			tasks.set(tasks.size() - i - 1, temp);
		}

		int numOfActivatedTasks = 0;
		for (int i = 0; i < tasks.size(); i++) {
			if (tasks.get(i).getDepartDate().getTime() >= (new Date())
					.getTime()) {
				numOfActivatedTasks++;
			}

			// remove code from airline
			String airlines = tasks.get(i).getAirlines();
			int vt = airlines.indexOf('-');
			while (vt > 0) {
				airlines = airlines.substring(0, vt - 2)
						+ airlines.substring(vt + 1, airlines.length());
				vt = airlines.indexOf('-');
			}
			tasks.get(i).setAirlines(airlines);
		}

		mav.addObject("tasks", tasks);
		mav.addObject("numOfTasks", tasks.size());
		mav.addObject("numOfActivatedTasks", numOfActivatedTasks);
		return mav;
	}

	@RequestMapping(value = "/create", method = RequestMethod.GET)
	public ModelAndView createTask(HttpSession session) {
		if (!SessionHelper.isLoggedIn(session)) {
			SessionHelper.setGoBackTaskpage(session, true);
			return new ModelAndView("redirect:/account/login.html");
		}
		ModelAndView mav = new ModelAndView("task/create");
		Parameters params = new Parameters();
		params.setTypeOfTrip(CONSTANTS.ONE_WAY);
		params.setNumStop(2);
		mav.addObject("parameters", params);
		return mav;
	}

	@RequestMapping(value = "/create", method = RequestMethod.POST)
	public ModelAndView postCreateNewTask(HttpSession session,
			@ModelAttribute @Valid Parameters params, BindingResult result,
			final RedirectAttributes redirectAttributes) {

		if (result.hasErrors()) {
			LOGGER.info(result.toString());
			ModelAndView mavError = new ModelAndView("task/create");
			mavError.addObject("parameters", params);
			return mavError;
		}
		TaskDTO task = new TaskDTO();
		ModelAndView mav = new ModelAndView("redirect:/task/create.html");
		Date nowTemp = new Date();
		@SuppressWarnings("deprecation")
		Date now = new Date(nowTemp.getYear(), nowTemp.getMonth(),
				nowTemp.getDate());
		try {
			Date departDate = Utils.SDF.parse(params.getOutBound().trim());
			task.setDepartDate(departDate);
		} catch (ParseException e) {
			LOGGER.info("Can't set Depart Date: ", e);
			// using Env
			redirectAttributes.addFlashAttribute("message",
					env.getRequiredProperty(PROPERTY_DAY_RETURN_INCORRECT));
			return mav;
		}
		if (CONSTANTS.ROUND_TRIP.equals(params.getTypeOfTrip())) {
			task.setTypeOfTrip(params.getTypeOfTrip());
			try {
				Date returnDate = Utils.SDF.parse(params.getInBound().trim());
				if (returnDate.getTime() < now.getTime()) {
					redirectAttributes
							.addFlashAttribute(
									"message",
									env.getRequiredProperty(PROPERTY_INBOUND_LESS_THAN_OUTBOUND));
					return mav;
				}
				task.setReturnDate(returnDate);
			} catch (ParseException e) {
				LOGGER.info("Can't set Return Date: ", e);
				// using Env
				redirectAttributes.addFlashAttribute("message",
						env.getRequiredProperty(PROPERTY_DAY_RETURN_INCORRECT));
				return mav;
			}

			try {
				Date departDate = Utils.SDF.parse(params.getOutBound().trim());
				task.setDepartDate(departDate);
			} catch (ParseException e) {
				LOGGER.info("Can't set Depart Date: ", e);
				// using Env
				redirectAttributes.addFlashAttribute("message",
						env.getRequiredProperty(PROPERTY_DAY_RETURN_INCORRECT));
				return mav;
			}
		} else {
			task.setTypeOfTrip(CONSTANTS.ONE_WAY);
		}
		task.setUserId(SessionHelper.getUserId(session));
		task.setName(params.getTaskName());
		task.setCurrencyCode(params.getCurrencyCode());
		if (params.getMaxPrice().trim() == "") {
			task.setMaxPrice(CONSTANTS.DEFAULT_MAX_PRICE);
		} else {
			task.setMaxPrice(Utils.convertToDouble(params.getMaxPrice()));
		}
		task.setMaxStops(params.getNumStop());
		task.setFlexibleDays(Integer.valueOf(params.getFlexibleDays()));
		task.setCabinClass(Utils.cabinClasses[Integer.parseInt(params
				.getCabinClass())]);

		// remove , character at the end
		String fromLocation = (params.getFromLocation() + "  ").replace(",  ",
				"").trim();
		String toLocation = (params.getToLocation() + "  ").replace(",  ", "")
				.trim();

		int pos1 = fromLocation.indexOf("-");
		int pos2 = toLocation.indexOf("-");
		int pos3 = fromLocation.lastIndexOf(",");
		int pos4 = toLocation.lastIndexOf(",");
		task.setFromCode(fromLocation.substring(0, pos1 - 1).trim());
		task.setToCode(toLocation.substring(0, pos2 - 1).trim());
		if (pos3 == -1) {
			task.setFromAirport(fromLocation.substring(pos1 + 2).trim());
			task.setToAirport(toLocation.substring(pos2 + 2).trim());
			task.setFromCountry(null);
			task.setToCountry(null);
		} else {
			task.setFromAirport(fromLocation.substring(pos1 + 2, pos3).trim());
			task.setToAirport(toLocation.substring(pos2 + 2, pos4).trim());
			task.setFromCountry(fromLocation.substring(pos3 + 2).trim());
			task.setToCountry(toLocation.substring(pos4 + 2).trim());
		}

		task.setAirlines(params.getAirlines());
		task.setTaskId(TaskDTO.makeTaskId(task));

		// convert from TaskDTO to Task and TaskUserId
		Task saveTask = new Task();
		TaskUserId taskUserId = new TaskUserId();

		saveTask = task.getTask(task);
		taskUserId = task.getTaskUserId(task);

		mav = new ModelAndView("redirect:/task/list.html");

		// check if task is already created
		Task temp = taskService.findByTaskId(saveTask.getTaskId());
		if (temp == null) {
			if (taskService.create(saveTask) != null
					&& taskUserIdService.create(taskUserId) != null) {
				// using Env
				redirectAttributes.addFlashAttribute("success",
						env.getRequiredProperty(PROPERTY_TASK_CREATE_SUCCESS));
			} else {
				// using Env
				redirectAttributes
						.addFlashAttribute(
								"message",
								env.getRequiredProperty(PROPERTY_TASK_WASNT_CREATE_SUCCESS));
			}
		} else {
			if (taskUserIdService.findByUserIdAndTaskId(taskUserId.getUserId(),
					taskUserId.getTaskId()) != null) {
				redirectAttributes
						.addFlashAttribute(
								"message",
								env.getRequiredProperty(PROPERTY_TASK_ALREADY_CREATED));
			}
			else {
				if (taskUserIdService.create(taskUserId) != null) {
					// using Env
					redirectAttributes.addFlashAttribute("success",
							env.getRequiredProperty(PROPERTY_TASK_CREATE_SUCCESS));
				} else {
					// using Env
					redirectAttributes
							.addFlashAttribute(
									"message",
									env.getRequiredProperty(PROPERTY_TASK_WASNT_CREATE_SUCCESS));
				}
			}
			
		}

		return mav;

	}

	@RequestMapping(value = "/delete", method = RequestMethod.POST)
	@ResponseBody
	public ModelAndView getDelete(@RequestBody String id, HttpSession session) {
		JSONObject object = new JSONObject(id);
		String taskId = object.getString("taskId");
		int userId = SessionHelper.getUserId(session);

		if (SessionHelper.isLoggedIn(session)) {
			try {
				TaskUserId temp = taskUserIdService.findByUserIdAndTaskId(
						userId, taskId);
				taskUserIdService.delete(temp.getId());

				if (taskUserIdService.findByTaskId(taskId).size() == 0) {
					Task task = taskService.findByTaskId(taskId);

					taskService.delete(task.getId());
				}

			} catch (TaskNotFoundException | TaskUserIdNotFoundException e) {
				LOGGER.info("Cant delete Task: ", e);
			}
		}
		return new ModelAndView("redirect:/task/list.html");
	}

	@RequestMapping(value = "/edit", method = RequestMethod.GET)
	public ModelAndView getEdit(HttpSession session,
			final RedirectAttributes redirectAttributes,
			@RequestParam(value = "taskId", required = true) String taskId) {

		if (!SessionHelper.isLoggedIn(session)) {
			SessionHelper.setGoBackTaskpage(session, true);
			return new ModelAndView("redirect:/account/login.html");
		}
		int userId = SessionHelper.getUserId(session);

		ModelAndView mav = new ModelAndView("task/edit");
		TaskUserId taskUserId = taskUserIdService.findByUserIdAndTaskId(userId,
				taskId);
		if (taskUserId == null) {
			return new ModelAndView("flight/search");
		}

		Task task = taskService.findByTaskId(taskId);

		TaskDTO taskDTO = new TaskDTO();
		taskDTO = taskDTO.getTaskDTO(task, taskUserId);

		if (taskDTO == null) {
			redirectAttributes.addFlashAttribute("message",
					env.getRequiredProperty(PROPERTY_TASK_UPDATE_NOT_FOUND));
			return new ModelAndView("redirect:/task/list.html");
		}

		Parameters params = new Parameters();

		params.setTaskName(taskDTO.getName());

		String outBound = Utils.SDF.format(taskDTO.getDepartDate());
		params.setOutBound(outBound);

		if (taskDTO.getReturnDate() != null) {
			String inBound = Utils.SDF.format(taskDTO.getReturnDate());
			params.setInBound(inBound);
		}

		params.setFromLocation(taskDTO.getFromCode());
		params.setToLocation(taskDTO.getToCode());
		params.setFromAirport(taskDTO.getFromAirport());
		params.setToAirport(taskDTO.getToAirport());
		params.setFromCountry(taskDTO.getFromCountry());
		params.setToCountry(taskDTO.getToCountry());

		params.setFlexibleDays("" + taskDTO.getFlexibleDays());

		params.setTypeOfTrip(taskDTO.getTypeOfTrip());
		if (taskDTO.getMaxPrice() == -1) {
			params.setMaxPrice(CONSTANTS.DEFAULT_MAX_PRICE + "");
		} else {
			params.setMaxPrice(taskDTO.getMaxPrice() + "");
		}
		params.setNumStop(taskDTO.getMaxStops());

		params.setAirlines(taskDTO.getAirlines());
		params.setCurrencyCode(taskDTO.getCurrencyCode());
		params.setCabinClass("0");
		for (int i = 0; i < 3; i++)
			if (Utils.cabinClasses[i].equals(taskDTO.getCabinClass())) {
				params.setCabinClass(i + "");
				break;
			}
		mav.addObject("parameters", params);
		SessionHelper.setSaveTaskId(session, task.getId() + "");
		SessionHelper.setSaveTaskUserId(session, taskUserId.getId() + "");
		return mav;
	}

	@RequestMapping(value = "/edit", method = RequestMethod.POST)
	public ModelAndView editTask(@ModelAttribute @Valid Parameters params,
			BindingResult result, final RedirectAttributes redirectAttributes,
			HttpSession session) {
		String saveTaskId = SessionHelper.getSaveTaskId(session);

		if (result.hasErrors()) {
			LOGGER.info(result.toString());
			ModelAndView mavError = new ModelAndView("task/edit");
			mavError.addObject("parameters", params);
			return mavError;
		}
		// test
		ObjectMapper mapper = new ObjectMapper();
		try {
			LOGGER.info(mapper.writeValueAsString(params));
		} catch (IOException e1) {
			LOGGER.error(e1);
		}

		// end test
		TaskDTO task = new TaskDTO();
		ModelAndView mav = new ModelAndView("task/edit.html?taskId="
				+ task.getTaskId());

		try {
			Date departDate = Utils.SDF.parse(params.getOutBound().trim());
			task.setDepartDate(departDate);
		} catch (ParseException e) {
			LOGGER.info("Can't set Depart Date", e);
			redirectAttributes.addFlashAttribute("message",
					env.getRequiredProperty(PROPERTY_DAY_RETURN_INCORRECT));
			return mav;
		}

		if (CONSTANTS.ROUND_TRIP.equals(params.getTypeOfTrip())) {
			task.setTypeOfTrip(params.getTypeOfTrip());
			try {
				Date returnDate = Utils.SDF.parse(params.getInBound().trim());
				task.setReturnDate(returnDate);
			} catch (ParseException e) {
				LOGGER.info("Cant set Return Day: ", e);
				redirectAttributes.addFlashAttribute("message",
						env.getRequiredProperty(PROPERTY_DAY_RETURN_INCORRECT));
				return mav;
			}

		} else {
			task.setTypeOfTrip(CONSTANTS.ONE_WAY);
		}
		task.setUserId(SessionHelper.getUserId(session));
		task.setName(params.getTaskName());
		task.setCurrencyCode(params.getCurrencyCode());

		task.setMaxStops(Integer.valueOf(params.getNumStop()));
		task.setFlexibleDays(Integer.valueOf(params.getFlexibleDays()));
		task.setCabinClass(Utils.cabinClasses[Integer.parseInt(params
				.getCabinClass())]);
		// update price
		LOGGER.info("Task controller: update price" + params.getMaxPrice());
		if (params.getMaxPrice().trim() == "") {
			task.setMaxPrice(CONSTANTS.DEFAULT_MAX_PRICE);
		} else {
			task.setMaxPrice(Utils.convertToDouble(params.getMaxPrice()));
		}
		// remove , character at the end
		String fromLocation = (params.getFromLocation() + "  ").replace(",  ",
				"").trim();
		String toLocation = (params.getToLocation() + "  ").replace(",  ", "")
				.trim();

		int pos1 = fromLocation.indexOf("-");
		int pos2 = toLocation.indexOf("-");
		int pos3 = fromLocation.lastIndexOf(",");
		int pos4 = toLocation.lastIndexOf(",");
		task.setFromCode(fromLocation.substring(0, pos1 - 1).trim());
		task.setToCode(toLocation.substring(0, pos2 - 1).trim());
		if (pos3 == -1) {
			task.setFromAirport(fromLocation.substring(pos1 + 2).trim());
			task.setToAirport(toLocation.substring(pos2 + 2).trim());
			task.setFromCountry(null);
			task.setToCountry(null);
		} else {
			task.setFromAirport(fromLocation.substring(pos1 + 2, pos3).trim());
			task.setToAirport(toLocation.substring(pos2 + 2, pos4).trim());
			task.setFromCountry(fromLocation.substring(pos3 + 2).trim());
			task.setToCountry(toLocation.substring(pos4 + 2).trim());
		}

		String[] airlinesArr = params.getAirlines().split(
				env.getRequiredProperty(PROPERTY_TOKEN_DILEMITER));
		String airlineNamesStr = "";
		for (int i = 0; i < airlinesArr.length; i++) {
			if (airlinesArr[i] == null || "".equals(airlinesArr[i]))
				continue;
			List<Airline> airs = airlineService.searchByCode(airlinesArr[i], 0);
			if (!airs.isEmpty()) {
				airlineNamesStr += airs.get(0).getName()
						+ env.getRequiredProperty(PROPERTY_TOKEN_DILEMITER);
			} else {
				airlineNamesStr += CONSTANTS.DELIMITER;
			}
		}
		airlineNamesStr = (airlineNamesStr + " ").replace(
				env.getRequiredProperty(PROPERTY_TOKEN_DILEMITER) + " ", "");

		task.setAirlines(params.getAirlines());
		task.setAirlineNames(airlineNamesStr);

		task.setTaskId(TaskDTO.makeTaskId(task));
		LOGGER.info("Task ID for all: " + task.getTaskId());

		mav = new ModelAndView("redirect:/task/list.html");
		boolean updateSuccess = false;
		try {
			task.setId(Integer.parseInt(SessionHelper.getSaveTaskId(session)));
			
			// if task with new taskId is not already exits in DB
			if (taskService.findByTaskId(task.getTask(task).getTaskId()) == null) {
				// check if old taskId is related to any user
				String taskIdStr = taskService.findById(Integer.parseInt(saveTaskId)).getTaskId();
				if (taskUserIdService.findByTaskId(taskIdStr).size() <= 1) {
					LOGGER.info("HERE");
					updateSuccess = taskService.update(task.getTask(task));
					
					task.setId(Integer.parseInt(SessionHelper
							.getSaveTaskUserId(session)));
					updateSuccess = taskUserIdService.update(task.getTaskUserId(task));
				}
				else {
					task.setId(-1);
					taskService.create(task.getTask(task));
					
					task.setId(Integer.parseInt(SessionHelper
							.getSaveTaskUserId(session)));
					updateSuccess = taskUserIdService.update(task.getTaskUserId(task));
				}
				
			}
			// if task with new taskId is already exits in DB
			else {
				// if user edit new task with already task they created
				if (taskUserIdService.findByUserIdAndTaskId(
						SessionHelper.getUserId(session), task.getTaskId()) != null) {
					redirectAttributes
					.addFlashAttribute(
							"message",
							env.getRequiredProperty(PROPERTY_TASK_ALREADY_CREATED));
					
					return mav;
				}
				else {
					// check if old task id is realted to another user
					String taskIdStr = taskService.findById(Integer.parseInt(saveTaskId)).getTaskId();
					if (taskUserIdService.findByTaskId(taskIdStr).size() <= 1) {
						taskService.delete(task.getId());
					}
					
					task.setId(Integer.parseInt(SessionHelper
							.getSaveTaskUserId(session)));
					updateSuccess = taskUserIdService.update(task.getTaskUserId(task));
				}
				
			}
			
		} catch (TaskNotFoundException | TaskUserIdNotFoundException e) {
			LOGGER.info("Task not found when update: " + e);
			redirectAttributes.addFlashAttribute("message",
					env.getRequiredProperty(PROPERTY_TASK_UPDATE_NOT_FOUND));
			return mav;

		}

		if (updateSuccess) {
			redirectAttributes.addFlashAttribute("success",
					env.getRequiredProperty(PROPERTY_TASK_UPDATE_SUCCESS));
		} else {
			redirectAttributes.addFlashAttribute("message",
					env.getRequiredProperty(PROPERTY_TASK_UPDATE_NOT_SUCCESS));
		}
		return mav;
	}

	@RequestMapping(value = { "/result" }, method = RequestMethod.POST)
	@ResponseBody
	public String getFlightFromTask(@RequestBody String taskId,
			HttpSession session) throws IOException, Exception {
		LOGGER.info("IN TASK RESULT CONTROLLER");

		String message;
		int index = 0;
		initService();
		JSONObject object = new JSONObject(taskId);
		String taskIdTemp = object.getString("taskId");
		Task task = taskService.findByTaskId(taskIdTemp);
		int userId = SessionHelper.getUserId(session);
		TaskUserId taskUserId = taskUserIdService.findByUserIdAndTaskId(userId,
				taskIdTemp);

		Parameters params = new Parameters();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
		// set task to parameters
		if (task == null) {
			message = "Cannot find !";
			return message;
		} else {
			params.setFromLocation(task.getFromCode());
			params.setToLocation(task.getToCode());
			params.setTypeOfTrip(task.getTypeOfTrip());
			params.setOutBound(sdf.format(task.getDepartDate()));
			if (task.getReturnDate() != null) {
				params.setInBound(sdf.format(task.getReturnDate()));
			} else {
				params.setInBound("");
			}
			if (task.getCabinClass().trim()
					.equalsIgnoreCase(CONSTANTS.CABIN_ALL_STRING)) {
				params.setCabinClass(CONSTANTS.CABIN_ALL_2);
			}
			if (task.getCabinClass().trim()
					.equalsIgnoreCase(CONSTANTS.CABIN_BUSSINESS_STRING)) {
				params.setCabinClass(CONSTANTS.CABIN_BUSSINESS_1);
			}
			if (task.getCabinClass().trim()
					.equalsIgnoreCase(CONSTANTS.CABIN_ECONOMY_STRING)) {
				params.setCabinClass(CONSTANTS.CABIN_ECONOMY_0);
			}
			params.setFlexibleDays("" + taskUserId.getFlexibleDays());
			params.setMaxPrice(taskUserId.getMaxPrice() + "");
			params.setCurrencyCode(taskUserId.getCurrencyCode());
			params.setAirlines(taskUserId.getAirlines());
		}

		// request to API
		List<Flight> flights;
		if (params.getCabinClass() == CONSTANTS.CABIN_ALL_2) {
			params.setCabinClass(CONSTANTS.CABIN_ECONOMY_0);
			flights = FlightRequesterService.getInstance().sendRequestFromTask(
					params);
			params.setCabinClass(CONSTANTS.CABIN_BUSSINESS_1);
			List<Flight> flightstemp = FlightRequesterService.getInstance()
					.sendRequestFromTask(params);
			params.setCabinClass(CONSTANTS.CABIN_ALL_2);
			for (int j = 0; j < flightstemp.size(); j++) {
				flights.add(flightstemp.get(j));
			}
		} else {
			flights = FlightRequesterService.getInstance().sendRequestFromTask(
					params);
		}
		FlightFactoryService flightFactoryService = new FlightFactoryService();
		flightFactoryService.setParameter(params);

		int idx = flights.size();

		int[][] sortedIndexes = new int[3][];
		for (int i = 0; i < 3; i++) {
			sortedIndexes[i] = new int[idx];
			for (int j = 0; j < idx; j++) {
				sortedIndexes[i][j] = j;
			}
		}
		// Sort by price
		int tmp;
		for (int i = 0; i < idx - 1; i++) {
			for (int j = i; j < idx; j++) {
				// Price
				if (Float.parseFloat(flights.get(sortedIndexes[0][i])
						.getPrice().getAmount()) > Float.parseFloat(flights
						.get(sortedIndexes[0][j]).getPrice().getAmount())) {

					tmp = sortedIndexes[0][i];
					sortedIndexes[0][i] = sortedIndexes[0][j];
					sortedIndexes[0][j] = tmp;
				}
			}
		}
		LOGGER.info("all data flights: " + flights.size());
		List<Flight> sendFlight = new ArrayList<>();
		for (int i = index; i < flights.size(); i++) {
			sendFlight.add(flights.get(sortedIndexes[0][i]));
		}
		// Convert flight list to json
		ObjectMapper mapper = new ObjectMapper();
		String jsonFlights = mapper.writeValueAsString(sendFlight);
		// save to session
		SessionHelper.removeFlights(session);
		SessionHelper.removeSortedIndexes(session);
		SessionHelper.setFlights(session, flights);
		SessionHelper.setSaveSortedIndexes(session, sortedIndexes);
		return jsonFlights;
	}
	
	@RequestMapping(value = { "/link-to-task" }, method = RequestMethod.POST)
	public ModelAndView linkToTaskFromNotification(@RequestParam(value="taskId", required=false) String taskId, HttpSession session,RedirectAttributes redirectAttribute) {
		LOGGER.info("IN TASK LINK");
		
		ModelAndView _mav = new ModelAndView("redirect:/task/list.html");
		if (SessionHelper.isLoggedIn(session)) {
			redirectAttribute.addFlashAttribute("taskId",taskId);
			LOGGER.info("taskId "+taskId);
		}else{
			SessionHelper.setGoBackSubscribe(session, true);
			_mav = new ModelAndView("account/login");
		}
		return _mav;
	}

}
